#pragma once
#include"term.h"
#include<stack>
#include<queue>
#include<cmath>


//判断输入的中追表达式是否合法
int IsCorrect(string s)

{
    int Size = s.size();
    int flag_parentheses = 0;
    int flag_zero = 0;
    int flag_point = 0;
    //判断括号输入数否合法
    for (int n = 0; n < Size; n++)
    {
        if (s[n] == '(')
        {
            flag_parentheses++;
        }

        else if (s[n] == ')')
        {
            flag_parentheses--;
        }

        if (flag_parentheses < 0)
        {
            return 0;
        }
    }

    if (flag_parentheses > 0)
    {
        return 0;
    }

    if (s[0] == '+' || s[0] == '-' || s[0] == '*' || s[0] == '/' || s[0] == '.')
    {
        return 0;
    }

    for (int n = 0; n < Size; n++)
    {
        if (s[n] == '1' || s[n] == '2' || s[n] == '3 ' || s[n] == ' 4' || s[n] == ' 5' || s[n] == ' 6' || s[n] == '7' || s[n] == '8' || s[n] == '9')
        {
            flag_zero = 1;
        }
        else if (s[n] == '0' && flag_zero == 0)
        {
            if (s[n + 1] == '.')
            {
                continue;
            }
            else
            {
                return 0;
            }
        }
        else if (s[n] == '+' || s[n] == '-' || s[n] == '*' || s[n] == '/')
        {
	  //判断输入是否合法
	  if (s[n + 1] == '+' || s[n + 1] == '-' || s[n + 1] == '*' || s[n + 1] == '/')
            {
                return 0;
            }
            flag_zero = 0;
            flag_point = 0;
        }
        else if (s[n] == '.')
        {
            if (flag_point == 1)
            {
                return 0;
            }
            else if (s[n + 1] == '+' || s[n + 1] == '-' || s[n + 1] == '*' || s[n + 1] == '/')
            {
                return 0;
            }
            flag_point = 1;
        }
	else if(s[n]!='+'&&s[n]!='-'&&s[n]!='/'&&s[n]!='*'&&s[n] != '1'&&s[n] != '2' && s[n] != '3 ' && s[n] != ' 4' && s[n] != ' 5' && s[n] != ' 6' && s[n] != '7' && s[n] != '8' && s[n] != '9')
	  {
	    if(s[n+1]=='.')
	      {
		return 0;
	      }
	  }
    }
    return 1;
}


//判断符号优先级，便于后续用栈计算后缀表达式
int insp(string s)

{
    if (s == "+" || s == "-")
    {
        return 1;
    }
    if (s == "*" || s == "/")
    {
        return 2;
    }
    if (s == "(" || s == ")")
    {
        return 0;
    }
    return 99;
}

int incp(string s)

{
    if (s == "+" || s == "-")
    {
        return 1;
    }
    if (s == "*" || s == "/")
    {
        return 2;
    }
    if (s == "(")
    {
        return 3;
    }
    if (s == ")")
    {
        return 0;
    }
    return 99;
}

//将字符串转化为后缀算数表达式
Terms TransPost(string s)

{
    int stringsize = s.size();
    Term* expression = new Term[stringsize];
    const char* exp_char = s.c_str();
    int flag_anumber = -1;
    int flag_upone = -1;
    int flag_havesmall = 0;
    double mark[40];
    int count = 0;
    if (IsCorrect(s) == 0)
    {
        Term T(0);
        expression[0] = T;
        Terms Ts(expression, 1);
        return Ts;
    }


    for (int n = 0; n < stringsize; n++)
    {
        if (exp_char[n] == '1' || exp_char[n] == '2' || exp_char[n] == '3' || exp_char[n] == '4' || exp_char[n] == '5' || exp_char[n] == '6' || exp_char[n] == '7' || exp_char[n] == '8' || exp_char[n] == '9' || exp_char[n] == '0')
        {
            flag_anumber++;
            mark[flag_anumber] = exp_char[n] - '0';
            if (n + 1 < stringsize)
            {
                if (exp_char[n + 1] == '1' || exp_char[n + 1] == '2' || exp_char[n + 1] == '3' || exp_char[n + 1] == '4' || exp_char[n + 1] == '5' || exp_char[n + 1] == '6' || exp_char[n + 1] == '7' || exp_char[n + 1] == '8' || exp_char[n + 1] == '9' || exp_char[n + 1] == '0')
                {
                    if (flag_havesmall == 0)
                    {
                        flag_upone = flag_anumber;
                    }
                    continue;
                }
                else if (exp_char[n + 1] == '.')
                {
                    flag_havesmall = 1;
                    flag_upone = flag_anumber;
                    flag_anumber = 19;
                    continue;
                }
                else if (exp_char[n + 1] == '+' || exp_char[n + 1] == '-' || exp_char[n + 1] == '*' || exp_char[n + 1] == '/' || exp_char[n + 1] == ')')
                {
                    if (flag_havesmall == 0)
                    {
                        flag_upone = flag_anumber;
                    }
                    continue;
                }
            }
            else if (n + 1 == stringsize)
            {
                if (flag_havesmall == 0)
                {
                    flag_upone = flag_anumber;
                }
            }
        }
        else if (exp_char[n] == '+' || exp_char[n] == '-' || exp_char[n] == '*' || exp_char[n] == '/' || exp_char[n] == ')')
        {
            if (exp_char[n - 1] != ')')
            {
                double floatnum = 0;
                int power_1 = flag_upone;
                for (int i = 0; i <= flag_upone; i++)
                {
                    floatnum += double(mark[i]) * pow(10, power_1);
                    power_1--;
                }
                if (flag_havesmall == 1)
                {
                    int power_2 = flag_anumber - 19;
                    for (int i = 0; i < (flag_anumber - 19); i++)
                    {
                        floatnum += mark[i + 20] * pow(0.1, i + 1);
                    }
                    flag_havesmall = 0;
                }

                Term a(1, "", floatnum);
                flag_anumber = -1;
                flag_upone = -1;
                flag_havesmall = 0;
                expression[count] = a;
                count++;
            }

            string st;
            st.push_back(exp_char[n]);
            Term b(-1, st, 0);
            expression[count] = b;
            count++;
        }
        else if (exp_char[n] == '(')
        {
            string st;
            st.push_back(exp_char[n]);
            Term b(-1, st, 0);
            expression[count] = b;
            count++;
        }
        if (n == stringsize - 1)
        {
            if (exp_char[n] != ')' && exp_char[n] != '(')
            {
                double floatnum = 0;
                int power_1 = flag_upone;
                for (int i = 0; i <= flag_upone; i++)
                {
                    floatnum += double(mark[i]) * pow(10, power_1);
                    power_1--;
                }
                if (flag_havesmall == 1)
                {
                    int power_2 = flag_anumber - 19;
                    for (int i = 0; i < (flag_anumber - 19); i++)
                    {
                        floatnum += mark[i + 20] * pow(0.1, i + 1);
                    }
                    flag_havesmall = 0;
                }

                Term a(1, "", floatnum);
                flag_anumber = -1;
                flag_upone = -1;
                flag_havesmall = 0;
                expression[count] = a;
                count++;
            }
        }
    }
    Terms Ts(expression, count);
    queue<Term> Stack_preTerm_temp;
    stack<Term> Stack_preTerm_process;
    int count_2 = count;
    for (int n = 0; n < count; n++)
    {
        if (Ts.terms[n].flag == 0)
        {
            cout << "erro";
            break;
        }
        else if (Ts.terms[n].flag == 1)
        {
            Stack_preTerm_temp.push(Ts.terms[n]);
        }
        else if (Ts.terms[n].flag == -1 && Ts.terms[n].Operator == ")")
        {
            for (; Stack_preTerm_process.top().Operator != "("; Stack_preTerm_process.pop())
            {
                Stack_preTerm_temp.push(Stack_preTerm_process.top());
            }
            Stack_preTerm_process.pop();
            count_2 -= 2;
        }
        else
        {
            if (!Stack_preTerm_process.empty())
            {
                for (int i = 0; i < Stack_preTerm_process.size(); i++)
                {
                    if (Stack_preTerm_process.empty())
                    {
                        break;
                    }
                    else if (insp(Stack_preTerm_process.top().Operator) >= incp(Ts.terms[n].Operator))
                    {
                        Stack_preTerm_temp.push(Stack_preTerm_process.top());
                        Stack_preTerm_process.pop();
                    }
                }
            }
            Stack_preTerm_process.push(Ts.terms[n]);
        }
    }
    for (; !Stack_preTerm_process.empty(); Stack_preTerm_temp.push(Stack_preTerm_process.top()), Stack_preTerm_process.pop());
    Term* exp_post = new Term[count_2];
    for (int n = 0; n < count_2; n++)
    {
        exp_post[n] = Stack_preTerm_temp.front();
        Stack_preTerm_temp.pop();
    }
    Terms TF(exp_post, count_2);
    return TF;
}



double calculate(Terms T)
{
    stack<double> Scal;
    for (int n = 0; n < T.Size; n++)
    {
        if (T.terms[n].flag == 1)
        {
            Scal.push(T.terms[n].Operand);
        }
        else if (T.terms[n].flag == -1)
        {
            if (T.terms[n].Operator == "+")
            {
                double a = Scal.top();
                Scal.pop();
                double b = Scal.top();
                Scal.pop();
                double c = a + b;
                Scal.push(c);
            }
            else if (T.terms[n].Operator == "-")
            {
                double a = Scal.top();
                Scal.pop();
                double b = Scal.top();
                Scal.pop();
                double c = b - a;
                Scal.push(c);
            }
           else if (T.terms[n].Operator == "*")
            {
                double a = Scal.top();
                Scal.pop();
                double b = Scal.top();
                Scal.pop();
                double c = a * b;
                Scal.push(c);
            }
            else if (T.terms[n].Operator == "/")
            {
                double a = Scal.top();
                Scal.pop();
                double b = Scal.top();
                Scal.pop();
                double c = b / a;
                Scal.push(c);
            }
        }
        else if (T.terms[n].flag == 0)
        {
            return -99999;
        }
    }
    return Scal.top();
}



double calculator(string s)

{
    Terms Ts = TransPost(s);
    double conclusion = calculate(Ts);
    return conclusion;
}
